/**
 * @file show_pic.c
 * @author pen
 * @brief 双屏幕图片查看器实现
 * 
 * 实现功能：
 * 1. 双屏幕图片展示（屏幕1和屏幕2）
 * 2. 双向循环链表管理图片路径
 * 3. 自动轮播与手动切换
 * 4. 触摸滑动切换（水平切换图片，垂直切换屏幕）
 * 5. 按钮控制切换
 * 
 * @version 0.1
 * @date 2025-10-16
 */

#include "show_pic.h"
#include "list.h"

// 定义全局变量
static lv_obj_t *img1 = NULL;  // 两个屏幕的图片对象
static lv_obj_t *img2 = NULL; 

static lv_timer_t *timer1 = NULL; // 两个屏幕的定时器
static lv_timer_t *timer2 = NULL; 

static lv_obj_t *screen1 = NULL; // 两个屏幕对象
static lv_obj_t *screen2 = NULL;
static lv_obj_t *current_screen = NULL; // 当前屏幕

// 添加全局变量记录触摸点
static lv_coord_t start_x = 0;
static lv_coord_t start_y = 0;

// 两个屏幕各自的链表
Dul_pLinkList head_screen1 = NULL; // 屏幕1链表头节点
Dul_pLinkList head_screen2 = NULL; // 屏幕2链表头节点

// 两个屏幕的当前节点
Dul_pLinkList current_node_screen1 = NULL;
Dul_pLinkList current_node_screen2 = NULL;

uint8_t total_images_screen1 = 0; // 屏幕1图片总数
uint8_t total_images_screen2 = 0; // 屏幕2图片总数

// 添加定时器状态变量
static bool screen1_timer_running = false;
static bool screen2_timer_running = false;

/**
 * @brief 初始化屏幕1的图片链表
 * 
 * 初始化链表
 * 链表的插入
 * 
 */
void init_image_list_screen1(void)
{
    // 初始化链表
    if (!InitList(&head_screen1)) 
    {
        printf("屏幕1链表初始化失败!\n");
        return;
    }
    
    // 插入图片路径到屏幕1的链表
    InsertLinst(head_screen1, 1, "S:/pen/showcar/pic/1.png");
    InsertLinst(head_screen1, 2, "S:/pen/showcar/pic/2.png");
    InsertLinst(head_screen1, 3, "S:/pen/showcar/pic/3.png");
    InsertLinst(head_screen1, 4, "S:/pen/showcar/pic/4.png");
    InsertLinst(head_screen1, 5, "S:/pen/showcar/pic/5.png");
    InsertLinst(head_screen1, 1, "S:/pen/showcar/pic/6.png");
    // 设置屏幕1的当前节点为第一个图片节点
    current_node_screen1 = head_screen1->next;
    
    // 计算屏幕1的图片总数
    Dul_pLinkList p = head_screen1->next;
    while (p != head_screen1) 
    {
        total_images_screen1++;
        p = p->next;
    }
    
    // printf("屏幕1图片链表初始化完成，共 %d 张图片\n", total_images_screen1);   //调试代码
}

/**
 * @brief 初始化屏幕2的图片链表
 * 
 * 初始化链表
 * 链表的插入
 * 
 */
void init_image_list_screen2(void)
{
    // 初始化链表
    if (!InitList(&head_screen2)) 
    {
        printf("屏幕2链表初始化失败!\n");
        return;
    }
    
    // 插入图片路径到屏幕2的链表
    InsertLinst(head_screen2, 1, "S:/pen/showcar/pic/7.png");
    InsertLinst(head_screen2, 2, "S:/pen/showcar/pic/8.png");
    InsertLinst(head_screen2, 3, "S:/pen/showcar/pic/9.png");
    InsertLinst(head_screen2, 4, "S:/pen/showcar/pic/10.png");
    InsertLinst(head_screen2, 4, "S:/pen/showcar/pic/11.png");
    InsertLinst(head_screen2, 4, "S:/pen/showcar/pic/12.png");

    // 设置屏幕2的当前节点为第一个图片节点
    current_node_screen2 = head_screen2->next;
    
    // 计算屏幕2的图片总数
    Dul_pLinkList p = head_screen2->next;
    while (p != head_screen2) 
    {
        total_images_screen2++;
        p = p->next;
    }
    
    // printf("屏幕2图片链表初始化完成，共 %d 张图片\n", total_images_screen2);       //调试代码
}

/**
 * @brief 清理屏幕1的图片链表资源
 * 
 * 释放屏幕1链表占用的内存，重置相关变量
 */
void cleanup_image_list_screen1(void)
{
    if (head_screen1 != NULL) 
    {
        ListDestory(&head_screen1);
        current_node_screen1 = NULL;
        total_images_screen1 = 0;
    }
}

/**
 * @brief 清理屏幕2的图片链表资源
 * 
 * 释放屏幕2链表占用的内存，重置相关变量
 */
void cleanup_image_list_screen2(void)
{
    if (head_screen2 != NULL) 
    {
        ListDestory(&head_screen2);
        current_node_screen2 = NULL;
        total_images_screen2 = 0;
    }
}

/**
 * @brief 显示指定屏幕的当前图片
 * 
 * 根据当前节点中的图片路径，更新对应屏幕的图片显示
 * 
 * @param screen_num 屏幕编号（1或2）
 */
void show_current_image(int screen_num)
{
    Dul_pLinkList current_node;
    lv_obj_t *img;
    uint8_t total_images;
    
    // 根据屏幕编号选择对应的变量
    if (screen_num == 1) 
    {
        current_node = current_node_screen1;
        img = img1;
        total_images = total_images_screen1;
    } 
    else 
    {
        current_node = current_node_screen2;
        img = img2;
        total_images = total_images_screen2;
    }
    

    if (current_node == NULL || total_images == 0) 
    {
        printf("屏幕 %d 没有可显示的图片\n", screen_num);
        return;
    }
    
    // 更新图片显示
    if (img != NULL) 
    {
        lv_img_set_src(img, current_node->data);
        // printf("屏幕 %d 显示图片: %s\n", screen_num, current_node->data);           //调试代码
    }
}

/**
 * @brief 切换到下一张图片（指定屏幕）
 * 
 * 在双向循环链表中移动到下一个节点，实现图片循环播放
 * 
 * @param screen_num 屏幕编号（1或2）
 */
void next_image(int screen_num)
{
    Dul_pLinkList *current_node;     //指向当前节点的指针
    Dul_pLinkList head;
    
    if (screen_num == 1) 
    {
        current_node = &current_node_screen1;
        head = head_screen1;
    } 
    else 
    {
        current_node = &current_node_screen2;
        head = head_screen2;
    }

    // 如果是最后一张，回到第一张
    if (*current_node == NULL || (*current_node)->next == head) 
    {
        *current_node = head->next;
    } 
    else 
    {
        *current_node = (*current_node)->next;
    }

    // 显示新图片
    show_current_image(screen_num);
}

/**
 * @brief 切换到上一张图片（指定屏幕）
 * 
 * 在双向循环链表中移动到前一个节点，实现图片逆向循环
 * 
 * @param screen_num 屏幕编号（1或2）
 */
void prev_image(int screen_num)
{
    Dul_pLinkList *current_node;
    Dul_pLinkList head;
    
    if (screen_num == 1) {
        current_node = &current_node_screen1;
        head = head_screen1;
    } else {
        current_node = &current_node_screen2;
        head = head_screen2;
    }
    
    // 如果是第一张，跳到最后一张
    if (*current_node == NULL || (*current_node)->prev == head) 
    {
        
        *current_node = head->prev;
    } 
    else 
    {
        *current_node = (*current_node)->prev;
    }

    // 显示新图片
    show_current_image(screen_num);
}

/**
 * @brief 屏幕1定时器回调函数
 * 
 * 每3秒自动切换到下一张图片
 * 
 * @param timer 定时器对象指针
 */
void timer_cb_screen1(lv_timer_t *timer) 
{
    if (total_images_screen1 == 0) 
    {
        return;
    }
    
    // 切换到下一张图片
    next_image(1);
}

/**
 * @brief 屏幕2定时器回调函数
 * 
 * 每3秒自动切换到下一张图片
 * 
 * @param timer 定时器对象指针
 */
void timer_cb_screen2(lv_timer_t *timer) 
{
    if (total_images_screen2 == 0) 
    {
        return;
    }
    
    // 切换到下一张图片
    next_image(2);
}

/**
 * @brief 切换到指定屏幕
 * 
 * 加载并显示指定的屏幕，更新当前屏幕状态。
 * 
 * @param screen_num 屏幕编号（1或2）
 */
void switch_screen(int screen_num)
{
    // 先停止所有屏幕定时器
    stop_screen_timers();
    if (screen_num == 1) 
    {
        lv_scr_load(screen1);                // 加载屏幕1
        current_screen = screen1;            // 更新屏幕指针
        // 启动屏幕1定时器
        start_screen_timers();
        // printf("切换到屏幕1\n");         
    } 
    else 
    {
        lv_scr_load(screen2);               // 加载屏幕2
        current_screen = screen2;           // 更新屏幕指针
        // 启动屏幕2定时器
        start_screen_timers();
        // printf("切换到屏幕2\n");
    }
}

/**
 * @brief 屏幕1上一张按钮事件处理
 * 
 * 响应按钮按下事件，切换到上一张图片
 * 
 * @param e 事件对象指针
 */
static void event_handler_prev_screen1(lv_event_t * e)
{
    lv_event_code_t code = lv_event_get_code(e);
    
    // 按下切换到上一张图片
    if(code == LV_EVENT_PRESSED) 
    {
        prev_image(1);
    }
}

/**
 * @brief 屏幕1下一张按钮事件处理
 * 
 * 响应按钮按下事件，切换到下一张图片
 * 
 * @param e 事件对象指针
 */
static void event_handler_next_screen1(lv_event_t * e)
{
    lv_event_code_t code = lv_event_get_code(e);
    
    // 按下切换到下一张图片
    if(code == LV_EVENT_PRESSED) 
    {
        next_image(1);
    }
}

/**
 * @brief 屏幕2上一张按钮事件处理
 * 
 * 响应按钮按下事件，切换到上一张图片
 * 
 * @param e 事件对象指针
 */
static void event_handler_prev_screen2(lv_event_t * e)
{
    lv_event_code_t code = lv_event_get_code(e);
    
    // 切换到上一张图片
    if(code == LV_EVENT_PRESSED) 
    {
        prev_image(2);
    }
}

/**
 * @brief 屏幕2下一张按钮事件处理
 * 
 * 响应按钮按下事件，切换到下一张图片
 * 
 * @param e 事件对象指针
 */
static void event_handler_next_screen2(lv_event_t * e)
{
    lv_event_code_t code = lv_event_get_code(e);
    
    // 切换到下一张图片
    if(code == LV_EVENT_PRESSED) 
    {
        next_image(2);
    }
}

/**
 * @brief 切换屏幕按钮事件处理
 * 
 * 在屏幕1和屏幕2之间切换。
 * 
 * @param e 事件对象指针
 */
static void event_handler_switch_screen(lv_event_t * e)
{
    lv_event_code_t code = lv_event_get_code(e);
    
    if(code == LV_EVENT_PRESSED) 
    {
        // 根据当前屏幕决定切换到哪个屏幕
        if (current_screen == screen1) 
        {
            switch_screen(2);
        } 
        else 
        {
            switch_screen(1);
        }
    }
}

/**
 * @brief 图片触摸按下事件处理
 * 
 * 记录触摸起始点坐标，用于后续滑动距离计算
 * 
 * @param e 事件对象指针
 */
static void on_img_pressed(lv_event_t *e)
{
    lv_event_code_t code = lv_event_get_code(e);
    
    if(code == LV_EVENT_PRESSED) 
    {
        lv_indev_t * indev = lv_indev_get_act();             // 获取当前输入设备
        if(indev) 
        {
            lv_point_t point;
            lv_indev_get_point(indev, &point);               // 获取触摸点坐标
            start_x = point.x;                               // 记录起始X坐标
            start_y = point.y;                               // 记录起始Y坐标
        }
    }
}

/**
 * @brief 图片触摸释放事件处理
 * 
 * 计算滑动距离和方向，根据滑动方向执行相应操作：
 *  水平滑动：切换图片（左滑下一张，右滑上一张）
 *  垂直滑动：切换屏幕（上滑/下滑切换屏幕）
 * 
 * @param e 事件对象指针
 */
static void on_img_released(lv_event_t *e)
{
    lv_event_code_t code = lv_event_get_code(e);
    
    if(code == LV_EVENT_RELEASED) 
    {
        lv_indev_t * indev = lv_indev_get_act();
        
        if(indev) 
        {
            lv_point_t point;
            lv_indev_get_point(indev, &point);               // 获取释放点坐标
            
            // 计算滑动距离
            lv_coord_t diff_x = point.x - start_x;           // X方向滑动距离
            lv_coord_t diff_y = point.y - start_y;           // Y方向滑动距离
            
            // 处理水平滑动 - 切换图片
            if(abs(diff_y) < 50)         // 垂直移动小于50
            {  
                if(diff_x > 80)          // 向右滑动超过80
                {  
                    // 切换上一张图片
                    if (current_screen == screen1) 
                    {
                        prev_image(1);
                    } 
                    else 
                    {
                        prev_image(2);
                    }
                }
                else if(diff_x < -80)   // 向左滑动超过80
                {  
                    // 切换下一张图片
                    if (current_screen == screen1) 
                    {
                        next_image(1);
                    } 
                    else 
                    {
                        next_image(2);
                    }
                }
            }

            // 处理垂直滑动 - 切换屏幕
            else if(abs(diff_x) < 50)    // 水平移动小于50
            {
                if(diff_y > 80)         // 向下滑动超过80
                {
                    if (current_screen == screen1) 
                    {
                        // switch_screen(2);
                    } 
                    else 
                    {
                        // 如果已经在屏幕2，向下滑动循环到屏幕1
                        switch_screen(1);
                    }
                }
                else if(diff_y < -80)   // 向上滑动超过80像素
                {
                    if (current_screen == screen1) 
                    {
                        // 如果已经在屏幕1，向上滑动循环到屏幕2
                        switch_screen(2);
                    } 
                    else 
                    {
                        // switch_screen(1);
                    }
                }
            }
        }
    }
}

/**
 * @brief 创建箭头图像按钮功能函数
 * 
 * 创建带有按下效果的图像按钮，用于图片切换控制
 * 
 * @param parent 父对象
 * @param x X坐标位置
 * @param y Y坐标位置
 * @param w 按钮宽度
 * @param h 按钮高度
 * @param pic_path 按钮图片路径
 * @return lv_obj_t* 创建的按钮对象指针
 */
lv_obj_t * lv_arrow_imgbtn(lv_obj_t *parent, int x, int y, int w, int h, char * pic_path)
{
    /* 创建按下状态的样式 */
    static lv_style_t style_pr; // 按下状态样式
    lv_style_init(&style_pr);
    lv_style_set_img_recolor_opa(&style_pr, LV_OPA_30);       // 透明度
    lv_style_set_img_recolor(&style_pr, lv_color_black());    // 颜色
    lv_style_set_transform_width(&style_pr, -5);  // 按下时稍微缩小
    lv_style_set_transform_height(&style_pr, -5);

    /* 创建图像按钮 */
    lv_obj_t * imgbtn = lv_imgbtn_create(parent);
    if(imgbtn == NULL) 
    {
        printf("lv_imgbtn_create fail\n");
        return NULL;
    }

    lv_obj_set_size(imgbtn, w, h); // 设置图片按键的大小w*h
    lv_imgbtn_set_src(imgbtn, LV_IMGBTN_STATE_RELEASED, NULL, pic_path, NULL);    // 设置按钮图片
    lv_obj_add_style(imgbtn, &style_pr, LV_STATE_PRESSED);                        // 应用按下样式

    // 设置按钮位置
    lv_obj_align(imgbtn, LV_ALIGN_TOP_LEFT, x, y);

    return imgbtn;
}

/**
 * @brief 设置屏幕1的UI界面
 * 
 * 创建屏幕1的所有UI元素：
 *  图片显示区域
 *  左右切换按钮
 *  屏幕切换按钮
 *  自动轮播定时器
 *  触摸事件处理
 */
void setup_screen1(void) 
{
    screen1 = lv_obj_create(NULL);
    
    // 创建图片对象
    img1 = lv_img_create(screen1);
    lv_obj_align(img1, LV_ALIGN_CENTER, 0, 0); // 居中显示
    
    // 设置图片对象可点击
    lv_obj_add_flag(img1, LV_OBJ_FLAG_CLICKABLE);

    // 设置对象大小（确保足够大以接收触摸事件）
    lv_obj_set_size(img1, 800, 480);

    // 显示初始图片
    show_current_image(1);
    
    // 创建定时器
    timer1 = lv_timer_create(timer_cb_screen1, 3000, NULL); // 每3秒切换一次图片

    // 创建切换上一张图片按钮
    lv_obj_t * left_btn = lv_arrow_imgbtn(screen1, 2, 240, 48, 48, "S:/pen/showcar/pic/left.png");
    lv_obj_add_event_cb(left_btn, event_handler_prev_screen1, LV_EVENT_PRESSED, NULL);    
    
    // 创建下一张按钮
    lv_obj_t * right_btn = lv_arrow_imgbtn(screen1, 750, 240, 48, 48, "S:/pen/showcar/pic/right.png"); 
    lv_obj_add_event_cb(right_btn, event_handler_next_screen1, LV_EVENT_PRESSED, NULL);  
    
    // 创建切换外观页面屏幕按钮
    lv_obj_t * apr_btn = lv_btn_create(screen1);
    lv_obj_set_size(apr_btn, LV_SIZE_CONTENT, LV_SIZE_CONTENT);
    lv_obj_set_style_bg_color(apr_btn, lv_color_hex(0xaba8ff), LV_STATE_DEFAULT);
    lv_obj_set_style_bg_opa(apr_btn, LV_OPA_50, LV_STATE_DEFAULT);
    lv_obj_add_event_cb(apr_btn, event_handler_switch_screen, LV_EVENT_ALL, NULL);
    lv_obj_align(apr_btn, LV_ALIGN_TOP_RIGHT, 0, 55);

    lv_obj_t * apr_label = lv_label_create(apr_btn);
    lv_label_set_text(apr_label, "外观");
    lv_obj_set_style_text_color(apr_label, lv_color_white(), LV_STATE_DEFAULT);
    lv_obj_set_style_text_font(apr_label, &chinese_ziku, 0);
    lv_obj_center(apr_label);
    
    
    // 添加触摸事件处理（按下和释放）
    lv_obj_add_event_cb(img1, on_img_pressed, LV_EVENT_PRESSED, NULL);
    lv_obj_add_event_cb(img1, on_img_released, LV_EVENT_RELEASED, NULL);

    // printf("屏幕1初始化完成\n");                                          //调试代码
}

/**
 * @brief 设置屏幕2的UI界面
 * 
 * 创建屏幕2的所有UI元素：
 *  图片显示区域
 *  左右切换按钮
 *  返回按钮
 *  屏幕标题
 *  自动轮播定时器
 *  触摸事件处理
 */
void setup_screen2(void) 
{
    screen2 = lv_obj_create(NULL);
    
    // 创建图片对象
    img2 = lv_img_create(screen2);
    lv_obj_align(img2, LV_ALIGN_CENTER, 0, 0); // 居中显示
    
    // 设置图片对象可点击
    lv_obj_add_flag(img2, LV_OBJ_FLAG_CLICKABLE);

    // 设置对象大小（确保足够大以接收触摸事件）
    lv_obj_set_size(img2, 800, 480);

    // 显示初始图片
    show_current_image(2);
    
    // 创建定时器
    timer2 = lv_timer_create(timer_cb_screen2, 3000, NULL); // 每3秒切换一次图片

    // 创建切换上一张图片按钮
    lv_obj_t * left_btn = lv_arrow_imgbtn(screen2, 2, 240, 48, 48, "S:/pen/showcar/pic/left.png");
    lv_obj_add_event_cb(left_btn, event_handler_prev_screen2, LV_EVENT_PRESSED, NULL);    
    
    // 创建下一张按钮
    lv_obj_t * right_btn = lv_arrow_imgbtn(screen2, 750, 240, 48, 48, "S:/pen/showcar/pic/right.png");
    lv_obj_add_event_cb(right_btn, event_handler_next_screen2, LV_EVENT_PRESSED, NULL);  
    
    // 创建回到屏幕1按钮
    lv_obj_t * rtn_btn = lv_btn_create(screen2);
    lv_obj_set_size(rtn_btn, LV_SIZE_CONTENT, LV_SIZE_CONTENT);
    lv_obj_set_style_bg_color(rtn_btn, lv_color_hex(0xaba8ff), LV_STATE_DEFAULT);
    lv_obj_set_style_bg_opa(rtn_btn, LV_OPA_50, LV_STATE_DEFAULT);
    lv_obj_add_event_cb(rtn_btn, event_handler_switch_screen, LV_EVENT_ALL, NULL);
    lv_obj_align(rtn_btn, LV_ALIGN_TOP_RIGHT, 0, 55);

    lv_obj_t * rtn_label = lv_label_create(rtn_btn);
    lv_label_set_text(rtn_label, "返回");
    lv_obj_set_style_text_color(rtn_label, lv_color_white(), LV_STATE_DEFAULT);
    lv_obj_set_style_text_font(rtn_label, &chinese_ziku, 0);
    lv_obj_center(rtn_label);
    
    // 添加屏幕标题
    lv_obj_t * label1 = lv_label_create(screen2);
    lv_label_set_text(label1, "外观");
    lv_obj_set_style_text_font(label1, &chinese_ziku, 0);
    lv_obj_set_style_text_color(label1, lv_color_hex(0xffffff), LV_STATE_DEFAULT);
    lv_obj_align(label1, LV_ALIGN_TOP_LEFT, 15, 100);
    
    // 添加滑动事件
    lv_obj_add_event_cb(img2, on_img_pressed, LV_EVENT_PRESSED, NULL);
    lv_obj_add_event_cb(img2, on_img_released, LV_EVENT_RELEASED, NULL);

    // printf("屏幕2初始化完成\n");                             //调试代码
}

/**
 * @brief 启动屏幕定时器
 */
void start_screen_timers(void)
{
    // 根据当前屏幕启动对应的定时器
    if (current_screen == screen1 && !screen1_timer_running) 
    {
        if (timer1) 
        {
            lv_timer_resume(timer1);
        } 
        else 
        {
            timer1 = lv_timer_create(timer_cb_screen1, 3000, NULL);
        }
        screen1_timer_running = true;
        // printf("屏幕1定时器启动\n");
    }
    
    if (current_screen == screen2 && !screen2_timer_running) 
    {
        if (timer2) 
        {
            lv_timer_resume(timer2);
        } 
        else 
        {
            timer2 = lv_timer_create(timer_cb_screen2, 3000, NULL);
        }
        screen2_timer_running = true;
        // printf("屏幕2定时器启动\n");
    }
}

/**
 * @brief 停止屏幕定时器
 */
void stop_screen_timers(void)
{
    if (screen1_timer_running && timer1) {
        lv_timer_pause(timer1);
        screen1_timer_running = false;
        // printf("屏幕1定时器停止\n");
    }
    
    if (screen2_timer_running && timer2) {
        lv_timer_pause(timer2);
        screen2_timer_running = false;
        // printf("屏幕2定时器停止\n");
    }
}

/**
 * @brief 检查屏幕1是否活跃
 */
bool is_screen1_active(void)
{
    return current_screen == screen1;
}

/**
 * @brief 检查屏幕2是否活跃
 */
bool is_screen2_active(void)
{
    return current_screen == screen2;
}

/**
 * @brief 初始化双屏幕
 * 
 * 完整的初始化流程：
 * 1. 初始化两个屏幕的图片链表
 * 2. 设置两个屏幕的UI界面
 * 3. 设置默认屏幕并加载
 */
void setup_dual_screen_image(void) 
{
    // 初始化两个屏幕的图片链表
    init_image_list_screen1();
    init_image_list_screen2();
    
    // 设置两个屏幕
    setup_screen1();
    setup_screen2();
    
    // 设置当前屏幕为屏幕1
    current_screen = screen1;
    lv_scr_load(screen1);
    
    screen1_timer_running = false;
    screen2_timer_running = false;
    // 调试代码
    // printf("双屏幕图片查看器初始化完成\n");
    // printf("屏幕1有 %d 张图片，屏幕2有 %d 张图片\n", total_images_screen1, total_images_screen2);  
}